package com.jdy.haoduoai.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.jdy.haoduoai.LeXiaoXiaoBanApp;

import org.droidparts.util.IOUtils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FileManager {

  public static String getSaveFilePath() {
    if (CommonUtil.hasSDCard()) {
      return CommonUtil.getRootFilePath() + "com.jdy.haoduoai/files/";
    } else {
      return CommonUtil.getRootFilePath() + "com.jdy.haoduoai/files";
    }
  }

  public enum FILEACCESSMODE {
    ADD, MODIFY, DELETE, LOAD, SAVE, OVERWRITE, APPEND
  };

  public enum ERRORCODE {
    OK, FILENOTEXIST, BADARGUMENTS, ACCESSFAIL
  };

  public static ERRORCODE checkCreateDir(String path) {
    if (path == null)
      return ERRORCODE.BADARGUMENTS;
    try {
      File file = new File(path);
      if (file.exists())
        return ERRORCODE.OK;

      boolean ret = file.mkdir();

      if (ret)
        return ERRORCODE.OK;
      else
        return ERRORCODE.ACCESSFAIL;
    } catch (Exception e) {
      e.printStackTrace();
      return ERRORCODE.ACCESSFAIL;
    }
  }

  public static long getFileSize(String fileName) {
    if (!isFileExist(fileName))
      return 0;
    File file = new File(fileName);
    if (!file.isFile())
      return 0;

    return file.length();
  }

  public static long getFileSize(String dir, String fileName) {
    if (!isFileExist(dir, fileName))
      return 0;
    File file = new File(dir, fileName);
    if (!file.isFile())
      return 0;

    return file.length();
  }

  public static long getDirSize(String dir) {
    if (!isFileExist(dir))
      return 0;
    File dirFile = new File(dir);
    if (!dirFile.isDirectory())
      return 0;

    String files[] = new File(dir).list();
    int total = 0;
    for (String str : files) {
      File file = new File(dir + str);
      total += file.length();
    }
    return total;
  }

  public static long getDirFileLength(String dir) {
    if (!isFileExist(dir))
      return 0;
    File dirFile = new File(dir);
    if (!dirFile.isDirectory())
      return 0;

    String files[] = new File(dir).list();
    return files.length;

  }

  public static long getDirFileLength(String dir, String fileName) {
    if (!isFileExist(dir))
      return 0;
    File dirFile = new File(dir);
    if (!dirFile.isDirectory())
      return 0;

    String files[] = new File(dir).list();
    return files.length;

  }

  public static boolean isFileExist(String fileFullName) {

    if (fileFullName == null)
      return false;

    File file = new File(fileFullName);
    return file.exists();
  }

  public static boolean isFileExist(String dir, String fileName) {

    if (fileName == null)
      return false;

    File file = new File(dir, fileName);
    return file.exists();
  }

  public static ERRORCODE deleteFile(String fileFullName) {

    if (fileFullName == null)
      return ERRORCODE.BADARGUMENTS;
    File file = new File(fileFullName);

    if (!file.exists())
      return ERRORCODE.FILENOTEXIST;

    file.delete();
    return ERRORCODE.OK;
  }

  public static ERRORCODE deleteFile(String dir, String fileName) {

    if (fileName == null)
      return ERRORCODE.BADARGUMENTS;
    File file = new File(dir, fileName);

    if (!file.exists())
      return ERRORCODE.FILENOTEXIST;

    file.delete();
    return ERRORCODE.OK;
  }

  /*
   * public static ERRORCODE saveStringFromOutputStreamByWriter(OutputStream
   * out,String encode) { if(out==null) return ERRORCODE.BADARGUMENTS;
   * 
   * try{ OutputStreamWriter osw=null; if (encode == null ||
   * "".equals(encode.trim())) osw = new OutputStreamWriter(out); else osw = new
   * OutputStreamWriter(out, encode); char buf[] = new char[1024]; int len;
   * //while ((len = osw.write(buf, offset, count)(buf)) != -1) {
   * //osw.write(buf, 0, len); //} osw.flush(); osw.close(); return
   * ERRORCODE.OK; } catch(Exception e) {
   * 
   * System.out.println("saveStringFromOutputStreamByWriter异常:"+e.toString());
   * e.printStackTrace(); return ERRORCODE.ACCESSFAIL; }
   * 
   * 
   * };
   */

  public static String getStringFromInputStreamByReader(InputStream in,
      String encode) {
    if (in == null)
      return null;

    InputStreamReader reader = null;

    try {
      long len = in.available();
      int length = (int) len;
      if (encode == null || "".equals(encode.trim())) {
        reader = new InputStreamReader(in);
      } else {

        reader = new InputStreamReader(in, encode);
      }

      char[] buffer = new char[length];
      reader.read(buffer, 0, length);
      return new String(buffer);

    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }

  };

  public static String getStringFromInputStream(InputStream in, String encode) {
    if (in == null)
      return null;

    try {
      BufferedInputStream bis = new BufferedInputStream(in);
      long len = in.available();
      int length = (int) len;
      byte bytearray[] = new byte[length];
      bis.read(bytearray, 0, length);

      if (encode != null && !"".equals(encode.trim()))
        return new String(bytearray, encode);
      return new String(bytearray);
    } catch (Exception e) {

      e.printStackTrace();
      return null;
    }

  };

  public static void saveFile(byte[] data, String fileFullName) {
    try {
      File file = new File(fileFullName);
      FileOutputStream fileOutputStream = new FileOutputStream(file);
      fileOutputStream.write(data);
      fileOutputStream.flush();
      fileOutputStream.close();
    } catch (Exception e) {

      e.printStackTrace();
    }
  }

  public static ERRORCODE saveTextFile(String content, String fileFullName,
      String encode) {

    if (fileFullName == null || content == null)
      return ERRORCODE.BADARGUMENTS;

    try {
      File file = new File(fileFullName);

      FileOutputStream fileOutputStream = new FileOutputStream(file);
      if (encode != null && !"".equals(encode.trim()))
        fileOutputStream.write(content.getBytes(encode));
      else
        fileOutputStream.write(content.getBytes());

      fileOutputStream.flush();
      fileOutputStream.close();
    } catch (Exception e) {
      e.printStackTrace();
      return ERRORCODE.ACCESSFAIL;
    }
    return ERRORCODE.OK;
  }

  public static ERRORCODE appendTextFile(String content, String fileFullName,
      String encode) {

    if (fileFullName == null || content == null)
      return ERRORCODE.BADARGUMENTS;

    try {
      File file = new File(fileFullName);

      if (!file.exists())
        return saveTextFile(content, fileFullName, encode);

      String[] original = new String[1];
      if (loadTextFile(original, fileFullName, encode) != ERRORCODE.OK
          || original[0] == null)
        return ERRORCODE.ACCESSFAIL;

      String newcontent = content;

      if (encode != null && !"".equals(encode.trim()))
        newcontent = new String(content.getBytes(), encode.trim());
      StringBuffer originalbuf = new StringBuffer(original[0]);
      StringBuffer totalbuf = originalbuf.append(newcontent);
      String totalstr = totalbuf.toString();

      FileOutputStream fileOutputStream = new FileOutputStream(file);
      if (encode != null && !"".equals(encode.trim()))
        fileOutputStream.write(totalstr.getBytes(encode));
      else
        fileOutputStream.write(totalstr.getBytes());

      fileOutputStream.flush();
      fileOutputStream.close();
    } catch (Exception e) {
      e.printStackTrace();
      return ERRORCODE.ACCESSFAIL;
    }
    return ERRORCODE.OK;
  }

  public static String loadTextFile(String fileFullName) {
    String content = "";
    try {
      File f = new File(fileFullName);
      FileInputStream fis = new FileInputStream(f);
      byte[] buf = new byte[fis.available()];
      fis.read(buf);
      content = new String(buf, "utf-8");
      fis.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return content;
  }

  public static ERRORCODE loadTextFile(String[] content, String fileFullName,
      String encode) {
    // System.out.println("Enter loadTextFile,fileFullName is " + fileFullName);

    if (fileFullName == null || content == null) {
      return ERRORCODE.BADARGUMENTS;
    }
    try {
      File f = new File(fileFullName);
      if (!f.exists())
        return ERRORCODE.FILENOTEXIST;

      FileInputStream fis = new FileInputStream(f);
      byte[] buf = new byte[fis.available()];
      fis.read(buf);
      if (encode == null || "".equals(encode.trim()))
        content[0] = new String(buf);
      else
        content[0] = new String(buf, encode);

      fis.close();
    } catch (Exception e) {
      e.printStackTrace();
      return ERRORCODE.ACCESSFAIL;
    }
    return ERRORCODE.OK;
  }

  public static ERRORCODE saveBinaryFile(String fileFullName, InputStream stream) {

    if (fileFullName == null || stream == null)
      return ERRORCODE.BADARGUMENTS;

    try {
      FileOutputStream fos = new FileOutputStream(fileFullName);
      byte data[] = new byte[1024];
      int count;
      while ((count = stream.read(data, 0, 1024)) != -1) {
        fos.write(data, 0, count);
      }
      fos.write(data, 0, data.length);
      fos.close();

      return ERRORCODE.OK;

    } catch (Exception e) {
      e.printStackTrace();
      return ERRORCODE.ACCESSFAIL;
    }
  }

  public static byte[] loadBinaryFile(String fileFullName) {

    if (fileFullName == null)
      return null;

    File file = new File(fileFullName);
    if (file == null || !file.exists())
      return null;

    try {
      FileInputStream fis = new FileInputStream(fileFullName);
      return IOUtils.readToByteArray(fis);

    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public static Object getListObject(String filename, Object obj) {
    if (filename == null || obj == null) {
      return null;
    }

    List<Object> list = new ArrayList<Object>();
    ERRORCODE ret = accessList(list, filename, FILEACCESSMODE.LOAD);

    if (ret != ERRORCODE.OK) {
      return null;
    }

    int index = list.indexOf(obj);
    if (index == -1) {
      return null;
    } else {
      return list.get(index);
    }
  }

  public static Object loadObject(String filename) {

    try {
      if (filename == null)
        return null;

      File fs = new File(filename);
      if (!fs.exists()) {
        return null;
      }

      FileInputStream objfile = new FileInputStream(fs);
      ObjectInputStream q = new ObjectInputStream(objfile);
      Object obj = q.readObject();
      q.close();
      return obj;
    } catch (Exception e) {
      return null;
    }
  }

  public static ERRORCODE saveObject(Object obj, String filename) {

    try {
      if (filename == null || obj == null)
        return ERRORCODE.BADARGUMENTS;

      File fs = new File(filename);
      if (fs.exists()) {
        fs.delete();
        fs.createNewFile();
      } else {
        fs.createNewFile();
      }

      FileOutputStream objfile = new FileOutputStream(fs);
      ObjectOutputStream p = new ObjectOutputStream(objfile);
      p.writeObject(obj);
      p.close();
      return ERRORCODE.OK;

    } catch (Exception e) {

      return ERRORCODE.ACCESSFAIL;

    }
  }

  @SuppressWarnings("unchecked")
  public static ERRORCODE accessList(List<Object> list, String filename,
      FILEACCESSMODE operation) {

    if (operation == FILEACCESSMODE.LOAD) {
      try {
        if (list == null || filename == null)
          return ERRORCODE.BADARGUMENTS;

        File fs = new File(filename);
        if (!fs.exists()) {
          return ERRORCODE.FILENOTEXIST;
        }

        FileInputStream objfile = new FileInputStream(fs);
        ObjectInputStream q = new ObjectInputStream(objfile);
        List<Object> tmp = (List<Object>) (q.readObject());

        int size = tmp.size();
        list.clear();

        for (int i = 0; i < size; i++) {
          list.add(tmp.get(i));
        }
        q.close();
        return ERRORCODE.OK;
      } catch (Exception e) {
        e.printStackTrace();
        return ERRORCODE.ACCESSFAIL;

      }
    } else if (operation == FILEACCESSMODE.SAVE) {
      try {
        if (list == null || filename == null)
          return ERRORCODE.BADARGUMENTS;

        File fs = new File(filename);

        if (fs.exists()) {
          fs.delete();
        }

        FileOutputStream objfile = new FileOutputStream(fs);

        ObjectOutputStream p = new ObjectOutputStream(objfile);

        p.writeObject(list);
        p.flush();
        objfile.close();
        return ERRORCODE.OK;
      } catch (Exception e) {
        e.printStackTrace();
        return ERRORCODE.ACCESSFAIL;
      }
    }

    return ERRORCODE.OK;
  }

  @SuppressWarnings("unchecked")
  public static ERRORCODE accessMap(Map<String, Object> map, String filename,
      FILEACCESSMODE operation) {

    if (operation == FILEACCESSMODE.LOAD) {
      try {
        if (map == null || filename == null)
          return ERRORCODE.BADARGUMENTS;

        File fs = new File(filename);
        if (!fs.exists()) {
          return ERRORCODE.FILENOTEXIST;
        }

        FileInputStream objfile = new FileInputStream(fs);
        ObjectInputStream q = new ObjectInputStream(objfile);
        Map<String, Object> tmp = (Map<String, Object>) (q.readObject());

        map.clear();
        map.putAll(tmp);
        q.close();
        return ERRORCODE.OK;
      } catch (Exception e) {
        e.printStackTrace();
        return ERRORCODE.ACCESSFAIL;

      }
    } else if (operation == FILEACCESSMODE.SAVE) {
      try {
        if (map == null || map.size() <= 0 || filename == null)
          return ERRORCODE.BADARGUMENTS;

        File fs = new File(filename);

        if (fs.exists()) {
          fs.delete();
        }

        FileOutputStream objfile = new FileOutputStream(fs);

        ObjectOutputStream p = new ObjectOutputStream(objfile);

        p.writeObject(map);
        p.flush();
        objfile.close();
        return ERRORCODE.OK;
      } catch (Exception e) {
        e.printStackTrace();
        return ERRORCODE.ACCESSFAIL;
      }
    }

    return ERRORCODE.OK;
  }

  public static ERRORCODE accessListObject(String filename, Object obj,
      FILEACCESSMODE operation) {
    if (obj == null || filename == null) {
      return ERRORCODE.BADARGUMENTS;
    }
    List<Object> list = new ArrayList<Object>();
    ERRORCODE ret = accessList(list, filename, FILEACCESSMODE.LOAD);

    if (operation == FILEACCESSMODE.ADD) {
      if (ret == ERRORCODE.FILENOTEXIST || ret == ERRORCODE.OK) {
        list.add(obj);
        return accessList(list, filename, FILEACCESSMODE.SAVE);
      }
      return ERRORCODE.ACCESSFAIL;
    } else if (operation == FILEACCESSMODE.MODIFY) {
      if (ret == ERRORCODE.FILENOTEXIST) {
        return accessListObject(filename, obj, FILEACCESSMODE.SAVE);
      } else if (ret == ERRORCODE.OK) {

        int index = list.indexOf(obj);
        if (index == -1) {
          list.add(obj);
        } else {
          list.set(index, obj);
        }
        return accessList(list, filename, FILEACCESSMODE.SAVE);
      } else {
        return ERRORCODE.ACCESSFAIL;
      }
    } else if (operation == FILEACCESSMODE.DELETE) {
      if (ret == ERRORCODE.OK) {
        int index = list.indexOf(obj);
        if (index == -1) {
          return ERRORCODE.FILENOTEXIST;
        } else {
          list.remove(index);
        }
        return accessList(list, filename, FILEACCESSMODE.SAVE);
      }
      return ERRORCODE.OK;
    } else {
      return ERRORCODE.BADARGUMENTS;
    }

  }

  public static Object getMapObject(String filename, String key) {
    if (filename == null || key == null)
      return null;

    Map<String, Object> map = new HashMap<String, Object>();
    ERRORCODE ret = accessMap(map, filename, FILEACCESSMODE.LOAD);

    if (ret != ERRORCODE.OK) {
      return null;
    }

    return map.get(key);

  }

  public static ERRORCODE accessMapObject(String filename, String key,
      Object obj, FILEACCESSMODE operation) {
    if (filename == null || key == null) {
      return ERRORCODE.BADARGUMENTS;
    }
    Map<String, Object> map = new HashMap<String, Object>();
    ERRORCODE ret = accessMap(map, filename, FILEACCESSMODE.LOAD);

    if (ret != ERRORCODE.OK) {
      return ERRORCODE.ACCESSFAIL;
    }

    if (operation == FILEACCESSMODE.ADD || operation == FILEACCESSMODE.MODIFY) {
      if (obj == null)
        return ERRORCODE.BADARGUMENTS;
      map.put(key, obj);

      return accessMap(map, filename, FILEACCESSMODE.SAVE);
    } else if (operation == FILEACCESSMODE.DELETE) {
      map.remove(key);
      return accessMap(map, filename, FILEACCESSMODE.SAVE);
    } else {
      return ERRORCODE.BADARGUMENTS;
    }

  }

  public static String getResourceString(Context context, int resId,
      String encode) {
    if (context == null)
      return null;

    return getStringFromInputStream(
        context.getResources().openRawResource(resId), encode);
  };

  public static String getResourceStringReader(Context context, int resId,
      String encode) {
    if (context == null)
      return null;

    return getStringFromInputStreamByReader(context.getResources()
        .openRawResource(resId), encode);
  };

  public static void createDirectory(String path) {
    if (path == null)
      return;

    File file = new File(path);
    if (!file.exists()) {
      file.mkdir();
    }
  }

  public static boolean removeDirectory(String path) {
    if (path == null)
      return false;

    File file = new File(path);
    try {
      if (file.exists()) {
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
          if (files[i].isDirectory()) {
            if (!removeDirectory(files[i].getAbsolutePath())) {
              return false;
            } else {
              files[i].delete();
            }
          } else {
            files[i].delete();
          }
        }

        file.delete(); // 删除空文件夹
        return true;
      }
    } catch (Exception e) {
      return false;
    }

    return true;
  }

  public static byte[] getBytes(InputStream in) {

    if (in == null) {
      return null;
    }
    ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
    byte[] imgdata = null;
    byte[] b = new byte[1024];
    int len = 0;
    try {
      while ((len = in.read(b, 0, 1024)) != -1) {
        bytestream.write(b, 0, len);
        bytestream.flush();
      }
      imgdata = bytestream.toByteArray();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      Log.e("getBytes", "IOException ", e);
    } finally {
      try {
        bytestream.close();
        if (in != null)
          in.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        Log.e("getBytes", "IOException ", e);
      }
    }
    return imgdata;
  }

  public static Bitmap getBitMapByByte(InputStream in, int sampleSize) {
    if (in != null) {
      byte[] bytes = getBytes(in);
      if (bytes != null) {
        if (sampleSize > 0) {
          BitmapFactory.Options opts = new BitmapFactory.Options();
          opts.inJustDecodeBounds = false;
          opts.inSampleSize = sampleSize;
          return BitmapFactory.decodeByteArray(getBytes(in), 0, bytes.length,
              opts);
        } else
          return BitmapFactory.decodeByteArray(getBytes(in), 0, bytes.length);
      }

    }
    return null;
  }

  public static Bitmap getBitMap(InputStream in, int sampleSize) {
    if (in != null) {
      if (sampleSize > 0) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = false;
        opts.inSampleSize = sampleSize;
        // return BitmapFactory.decodeStream(in,null,opts);
        return BitmapFactory.decodeStream(in);
      } else
        return BitmapFactory.decodeStream(in);

    }
    return null;
  }

  public static byte[] ReadDataFromAssetfile(String fileName) {
    InputStream fIn = null;
    byte[] data = null;
    try {
      fIn = LeXiaoXiaoBanApp.getAppContext().getResources().getAssets()
          .open(fileName);

      data = getBytes(fIn);
    } catch (Exception e) {
      e.getMessage();
    } finally {
      try {
        if (fIn != null)
          fIn.close();
      } catch (Exception e2) {
        e2.getMessage();
      }
    }
    return data;
  }

  public static String ReadFromAssetfile(String fileName) {
    StringBuilder ReturnString = new StringBuilder();
    InputStream fIn = null;
    InputStreamReader isr = null;
    BufferedReader input = null;
    try {
      fIn = LeXiaoXiaoBanApp.getAppContext().getResources().getAssets()
          .open(fileName);
      isr = new InputStreamReader(fIn);
      input = new BufferedReader(isr);
      String line = "";
      while ((line = input.readLine()) != null) {
        ReturnString.append(line);
      }
    } catch (Exception e) {
      e.getMessage();
    } finally {
      try {
        if (isr != null)
          isr.close();
        if (fIn != null)
          fIn.close();
        if (input != null)
          input.close();
      } catch (Exception e2) {
        e2.getMessage();
      }
    }
    return ReturnString.toString();
  }
}
